package com.sise.netty.断线重连;

import com.sise.netty.Gzip流应用.GzipUtil;
import com.sise.netty.断线重连.dto.RequestDto;
import com.sise.netty.断线重连.serialHandler.MarshallingCodeHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.WriteTimeoutHandler;

import java.io.IOException;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author idea
 * @data 2019/4/14
 */
public class Client {

    private EventLoopGroup group = null;

    private Bootstrap bootstrap = null;

    private ChannelFuture channelFuture = null;

    private Client() {
        init();
    }

    /**
     * 初始化资源，并且对于bootstrap进行配置绑定
     */
    private void init() {
        group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        bootstrap.group(group);
        bootstrap.channel(NioSocketChannel.class);
    }


    public void channelHandle(ChannelHandler... channelHandlers) throws InterruptedException {
        this.bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(MarshallingCodeHandler.buildMarshallingEncoder());
                ch.pipeline().addLast(MarshallingCodeHandler.buildMarshallingDecoder());
                //当三秒没有发生写操作的时候就会自动断线
                ch.pipeline().addLast(new WriteTimeoutHandler(3));
                ch.pipeline().addLast(channelHandlers);
            }
        });
    }

    /**
     * 关闭资源
     */
    public void release() {
        this.group.shutdownGracefully();
    }


    /**
     * 获得通道连接
     *
     * @param host
     * @param port
     * @return
     * @throws InterruptedException
     */
    public ChannelFuture getChannelFuture(String host, int port) throws InterruptedException {
        if (channelFuture == null) {
            channelFuture = this.bootstrap.connect(host, port).sync();
        }
        if (!channelFuture.channel().isActive()) {
            channelFuture = this.bootstrap.connect(host, port).sync();
        }
        return channelFuture;
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Client client = null;
        ChannelFuture future = null;
        String host = "127.0.0.1";
        int port = 9090;
        client = new Client();
        client.channelHandle(new ClientHandle());
        future = client.getChannelFuture(host, port);
        for (int i = 0; i < 3; i++) {
            byte[] mess = ("test" + i).getBytes();
            RequestDto requestDto = new RequestDto(new Random().nextInt(10000), GzipUtil.zip(mess), new Date());
            future.channel().writeAndFlush(requestDto);
            TimeUnit.SECONDS.sleep(2);
        }

        TimeUnit.SECONDS.sleep(5);
        future = client.getChannelFuture(host, port);
        byte[] mess = ("test" + 4).getBytes();
        RequestDto requestDto = new RequestDto(new Random().nextInt(10000),  GzipUtil.zip(mess), new Date());
        future.channel().writeAndFlush(requestDto);
    }


}
